﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "BuilderPattern.generated.h"

/**	建造者模式 Builder Pattern
*	描述
 *		建造者模式，又称生成器模式。是将一个复杂的对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示。
 *		建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离，客户端无需知道复杂对象的内部组成与装配方式，主需要知道所需的建造者即可。类似工厂方法，但是建造者模式返回一个完整的复杂产品，而抽象工厂模式则返回一系列相关的产品。以汽车为例，工厂方法可以看成不同汽车配件的生成，而建造者模式则可以看成时汽车的组装
 *	套路
 *		Builder：抽象建造者
 *			为创建一个产品对象的各个部件指定抽象接口，一般包含两个接口方法：一个用于创建复杂对象的各个部件；另一个用于返回生成好的复杂对象。它就可以是抽象类，也可以是接口。
 *		ConcreteBuilder：具体建造者
 *			实现了Builder接口，即实现了各个部件的具体构造和装配方法，定义并明确其所创建的复杂对象。
 *		Product：产品角色
 *			被构建的复杂对象，包含多个组成部件。
 *		Director：指挥者
 *			负责安排复杂对象的建造次序，指挥者与抽象建造者之间存在关联关系，可以在其Construct()方法中调用建造者对象的部件构造和装配方法，完成复杂对象的建造。
 *	使用场景
 *		需要生成的产品对象有复杂的内部结构，这些产品对象通常包含多个成员属性。
 *		需要生成的产品对象的属性相互依赖，需要指定其生成顺序。
 *		对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类，将创建过程封装在指挥者类中，而不在建造者类中。
 *		隔离复杂对象的创建和使用，并使得相同的创建过程可以创建不同的产品。
 *	示例
 *		不同门派角色生成，具有不同的服装、武器、发型
 *		不同地图生成，如道路、植被、天气、怪物。
 *		武器组装
 *	优缺点
 *		优点
 *			客户端不必知道产品内部组成的细节，将产品本身与产品的创建过程解耦，使得相同的创建过程可以创建不同的产品对象。
 *			用户使用不同的具体建造者即可得到不同的产品对象 。
 *			可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中，使得创建过程更加清晰，也更方便使用程序来控制创建过程。
 *			增加新的具体建造者无须修改原有类库的代码，指挥者类针对抽象建造者类编程，系统扩展方便，符合“开闭原则”。
 *		缺点
 *			建造者模式所创建的产品一般具有较多的共同点，其组成部分相似。如果产品之间的差异性很大，则不适合使用，因此其使用范围受到一定的限制。
 *			如果产品的内部变化复杂，可能会导致需要定义很多具体建造者类来实现这种变化，导致系统变得很庞大。
 */

// 复杂产品 —— 门派角色
UCLASS(Blueprintable, BlueprintType)
class MISCELLANEOUSPROJECT_API UBuilderSectPlayer : public UObject
{
	GENERATED_BODY()
public:
	// 门派
	FString Sect = TEXT("None");
	// 性别
	FString Render = TEXT("None");
	// 服装
	FString Costume = TEXT("None");
	// 武器
	FString Weapon = TEXT("None");

	// 展示信息
	void ShowInfo()
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" %s %s %s %s"), *Sect, *Render, *Costume, *Weapon);
	}
};

// 抽象建造者 —— 角色构造器
UCLASS(Abstract)
class MISCELLANEOUSPROJECT_API UBuilderSectPlayerBuilder : public UObject
{
	GENERATED_BODY()
public:
	// 构造函数创建复杂角色实例
	UBuilderSectPlayerBuilder() { SectPlayer = NewObject<UBuilderSectPlayer>(); }

	// 各个构建部分
	virtual void BuilderSect() {}
	virtual void BuilderRender() {}
	virtual void BuilderCostume() {}
	virtual void BuilderWeapon() {}

	// 返回角色实例
	UBuilderSectPlayer* GetPlayer() { return SectPlayer; }
protected:
	UBuilderSectPlayer* SectPlayer;
};

// 具体建造者 —— 纯阳角色构造器
UCLASS(Blueprintable, BlueprintType)
class MISCELLANEOUSPROJECT_API UBuilderChunYangSectPlayerBuilder : public UBuilderSectPlayerBuilder
{
	GENERATED_BODY()
public:
	virtual void BuilderSect() override { SectPlayer->Sect = TEXT("纯阳门派"); }
	virtual void BuilderRender() override { SectPlayer->Render = TEXT("男"); }
	virtual void BuilderCostume() override { SectPlayer->Costume = TEXT("纯阳服装"); }
	virtual void BuilderWeapon() override { SectPlayer->Weapon = TEXT("纯阳武器"); }
};

// 具体建造者 —— 七秀角色构造器
UCLASS(Blueprintable, BlueprintType)
class MISCELLANEOUSPROJECT_API UBuilderQiXiuSectPlayerBuilder : public UBuilderSectPlayerBuilder
{
	GENERATED_BODY()
public:
	virtual void BuilderSect() override { SectPlayer->Sect = TEXT("七秀门派"); }
	virtual void BuilderRender() override { SectPlayer->Render = TEXT("女"); }
	virtual void BuilderCostume() override { SectPlayer->Costume = TEXT("七秀服装"); }
	virtual void BuilderWeapon() override { SectPlayer->Weapon = TEXT("七秀武器"); }
};

// 指挥者(Director) —— 角色创建指挥者
UCLASS(Blueprintable, BlueprintType)
class MISCELLANEOUSPROJECT_API UBuilderPlayerCreateDirectory : public UBuilderSectPlayerBuilder
{
	GENERATED_BODY()
public:
	UBuilderSectPlayer* Construct(UBuilderSectPlayerBuilder* SectPlayerBuilder)
	{
		// 逐步构建复杂角色
		SectPlayerBuilder->BuilderSect();
		SectPlayerBuilder->BuilderRender();
		SectPlayerBuilder->BuilderCostume();
		SectPlayerBuilder->BuilderWeapon();

		return SectPlayerBuilder->GetPlayer();
	}
};

// 调用测试用的Actor
UCLASS()
class MISCELLANEOUSPROJECT_API APlayerBuilder : public AActor
{
	GENERATED_BODY()
public:

	virtual void BeginPlay() override
	{
		// 创建指挥者
		UBuilderPlayerCreateDirectory* PlayerCreateDirectory = NewObject<UBuilderPlayerCreateDirectory>();

		// 指定纯阳角色构造器生成角色
		UBuilderSectPlayer* ChunYangPlayer = PlayerCreateDirectory->Construct(NewObject<UBuilderChunYangSectPlayerBuilder>());
		ChunYangPlayer->ShowInfo();

		// 指定七秀角色构造器生成角色
		UBuilderSectPlayer* QiXiuPlayer = PlayerCreateDirectory->Construct(NewObject<UBuilderQiXiuSectPlayerBuilder>());
		QiXiuPlayer->ShowInfo();
	}
};
